package edu.ynu.se.xiecheng.achitectureclass.service;

import edu.ynu.se.xiecheng.achitectureclass.dao.*;
import edu.ynu.se.xiecheng.achitectureclass.dto.SensorDataDTO;
import edu.ynu.se.xiecheng.achitectureclass.entity.*;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.sql.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Service
public class SensorDataService {

    private static final String SENSOR_DATA_URL = "https://fbox360.com/api/v2/dmon/value/get?boxNo=%s";

    @Autowired
    private FboxService fboxService;

    private final RestTemplate restTemplate;

    @Autowired
    private DeviceDao deviceDao;
    @Autowired
    private SoilMoistureDataDao soilMoistureDataDao;
    @Autowired
    private SoilTemperatureDataDao soilTemperatureDataDao;
    @Autowired
    private SoilNitrogenDataDao soilNitrogenDataDao;
    @Autowired
    private AirTemperatureDataDao airTemperatureDataDao;
    @Autowired
    private CarbonDioxideDataDao carbonDioxideDataDao;

    public SensorDataService(RestTemplateBuilder builder) {
        this.restTemplate = builder.build();
    }

    /**
     * 获取传感器数据并存储到数据库
     *
     * @param boxNo    设备编号
     * @param sensorIds 传感器 ID 列表
     */
    public void fetchSensorData(String boxNo, List<String> sensorIds) {
        String url = String.format(SENSOR_DATA_URL, boxNo);
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_JSON);
        headers.set("Authorization", "Bearer " + fboxService.getAccessToken()); // 使用缓存的 Token

        SensorRequest requestObj = new SensorRequest(sensorIds);
        HttpEntity<SensorRequest> request = new HttpEntity<>(requestObj, headers);

        ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class);

        if (response.getStatusCode().is2xxSuccessful()) {
            try {
                JSONArray dataArray = new JSONArray(response.getBody());

                // 用于存储所有生成的 Device 对象
                Map<String, Device> deviceMap = new HashMap<>();

                // 第一步：解析 API 响应，将数据存储到 Device 中
                for (int i = 0; i < dataArray.length(); i++) {
                    JSONObject data = dataArray.getJSONObject(i);
                    String sensorId = data.getString("id");
                    String sensorName = data.getString("name");
                    double value = data.getDouble("value");

                    // 获取或创建 Device 对象
                    Device device = deviceMap.get(sensorId);
                    if (device == null) {
                        device = new Device();
                        device.setSensorId(sensorId);
                        device.setName(sensorName);
                        device.setMonitoringAddress("未知地址"); // 根据实际情况设置
                        device.setCreateTime(new Date(System.currentTimeMillis()));

                        // 根据 sensorId 设置 unit 和 category
                        switch (sensorId) {
                            case "327061330933584660": // 土壤含水率
                                device.setUnit("%");
                                device.setCategory("土壤传感器");
                                break;
                            case "327061330933584661": // 土壤温度
                                device.setUnit("℃");
                                device.setCategory("土壤传感器");
                                break;
                            case "327061330932536077": // 土壤氮含量
                                device.setUnit("mg/kg");
                                device.setCategory("土壤传感器");
                                break;
                            case "327061330933584659": // 空气温度
                                device.setUnit("℃");
                                device.setCategory("空气传感器");
                                break;
                            case "327061330932536081": // 二氧化碳
                                device.setUnit("ppm");
                                device.setCategory("空气传感器");
                                break;
                            default:
                                System.out.println("Unknown sensor ID: " + sensorId);
                                break;
                        }

                        deviceMap.put(sensorId, device);
                    }

                    // 根据 sensorId 处理不同的传感器数据
                    switch (sensorId) {
                        case "327061330933584660": // 土壤含水率
                            SoilMoistureData soilMoistureData = new SoilMoistureData();
                            soilMoistureData.setValue(value);
                            soilMoistureData.setDevice(device);
                            soilMoistureData.setCreateTime(new Date(System.currentTimeMillis()));
                            device.getSoilMoistureDataList().add(soilMoistureData);
                            break;
                        case "327061330933584661": // 土壤温度
                            SoilTemperatureData soilTemperatureData = new SoilTemperatureData();
                            soilTemperatureData.setValue(value);
                            soilTemperatureData.setDevice(device);
                            soilTemperatureData.setCreateTime(new Date(System.currentTimeMillis()));
                            device.getSoilTemperatureDataList().add(soilTemperatureData);
                            break;
                        case "327061330932536077": // 土壤氮含量
                            SoilNitrogenData soilNitrogenData = new SoilNitrogenData();
                            soilNitrogenData.setValue(value);
                            soilNitrogenData.setDevice(device);
                            soilNitrogenData.setCreateTime(new Date(System.currentTimeMillis()));
                            device.getSoilNitrogenDataList().add(soilNitrogenData);
                            break;
                        case "327061330933584659": // 空气温度
                            AirTemperatureData airTemperatureData = new AirTemperatureData();
                            airTemperatureData.setValue(value);
                            airTemperatureData.setDevice(device);
                            airTemperatureData.setCreateTime(new Date(System.currentTimeMillis()));
                            device.getAirTemperatureDataList().add(airTemperatureData);
                            break;
                        case "327061330932536081": // 二氧化碳
                            CarbonDioxideData carbonDioxideData = new CarbonDioxideData();
                            carbonDioxideData.setValue(value);
                            carbonDioxideData.setDevice(device);
                            carbonDioxideData.setCreateTime(new Date(System.currentTimeMillis()));
                            device.getCarbonDioxideDataList().add(carbonDioxideData);
                            break;
                        default:
                            System.out.println("Unknown sensor ID: " + sensorId);
                            break;
                    }
                }

                // 第二步：将所有 Device 和传感器数据保存到数据库
                for (Device device : deviceMap.values()) {
                    deviceDao.save(device); // 保存 Device
                    // 保存土壤湿度数据
                    soilMoistureDataDao.saveAll(device.getSoilMoistureDataList());
                    // 保存土壤温度数据
                    soilTemperatureDataDao.saveAll(device.getSoilTemperatureDataList());
                    // 保存土壤氮含量数据
                    soilNitrogenDataDao.saveAll(device.getSoilNitrogenDataList());
                    // 保存空气温度数据
                    airTemperatureDataDao.saveAll(device.getAirTemperatureDataList());
                    // 保存二氧化碳数据
                    carbonDioxideDataDao.saveAll(device.getCarbonDioxideDataList());
                }

                // 第三步：对 Device 进行查找或其他操作
                for (Device device : deviceMap.values()) {
                    System.out.println("Device ID: " + device.getId() + ", Sensor ID: " + device.getSensorId());
                    // 这里可以添加其他对 Device 的操作
                }
            } catch (JSONException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("Failed to fetch sensor data. HTTP Status: " + response.getStatusCode());
        }
    }

    /**
     * 获取各个设备的最新数据
     */
    public SensorDataDTO getLatestData() {
        SensorDataDTO dto = new SensorDataDTO();
        dto.setSoilMoisture(soilMoistureDataDao.findTopByOrderByCreateTimeDesc());
        dto.setSoilTemperature(soilTemperatureDataDao.findTopByOrderByCreateTimeDesc());
        dto.setSoilNitrogen(soilNitrogenDataDao.findTopByOrderByCreateTimeDesc());
        dto.setAirTemperature(airTemperatureDataDao.findTopByOrderByCreateTimeDesc());
        dto.setCarbonDioxide(carbonDioxideDataDao.findTopByOrderByCreateTimeDesc());
        return dto;
    }

    /**
     * 获取某个设备的过去数据（支持分页）
     */
    public Page<?> getHistoricalData(String sensorType, int page, int size) {
        Pageable pageable = PageRequest.of(page, size);
        switch (sensorType.toLowerCase()) {
            case "soilmoisture":
                return soilMoistureDataDao.findAllByOrderByCreateTimeDesc(pageable);
            case "soiltemperature":
                return soilTemperatureDataDao.findAllByOrderByCreateTimeDesc(pageable);
            case "soilnitrogen":
                return soilNitrogenDataDao.findAllByOrderByCreateTimeDesc(pageable);
            case "airtemperature":
                return airTemperatureDataDao.findAllByOrderByCreateTimeDesc(pageable);
            case "carbondioxide":
                return carbonDioxideDataDao.findAllByOrderByCreateTimeDesc(pageable);
            default:
                throw new IllegalArgumentException("Invalid sensor type: " + sensorType);
        }
    }
}